package in.muton.edushare.grading.panels;

import in.muton.edushare.helper.TinyMCEHelper;
import in.muton.edushare.pages.common.EdusharePanel;
import in.muton.edushare.pages.coursepages.CourseGrading;
import in.muton.edushare.wicket.converters.choicerenderers.GenericRenderer;

import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;

import com.edushare.common.dao.GradingItemDAO;
import com.edushare.common.util.StringUtil;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.GradingItem;
import com.edushare.common.vo.ItemGrade;

public class NewGradeItemPanel extends EdusharePanel {
	private static final long serialVersionUID = 3001553783455828607L;
	private static final Log log = LogFactory.getLog(NewGradeItemPanel.class);

	public NewGradeItemPanel(String id, CourseGrading page, CourseInstances inst) {
		super(id, page);
		this.gradePage = page;
		init();
	}

	private void init() {
		typeRenderer = new GenericRenderer<Integer>(typeMap,
				GradingItem.ITEM_EXAM);
		gradeTypeRenderer = new GenericRenderer<Integer>(gradeTypeMap,
				GradingItem.GRADE_MARKS);
		initModels();
		Form<Void> f = new Form<Void>("newForm") {
			private static final long serialVersionUID = 5088219220769537816L;
			@Override
			public void onSubmit() {
				if (!verify())
					return;
				if (gItem == null)
					submit();
				else
					submit(gItem);
				setError("");
				setGcDesc("");
				setGcMaxMarks("");
				setGcTitle("");
				setGcWeightage("");
				gradePage.setActivePanel(CourseGrading.GRADE_COMPONENTS);
			}
		};
		add(f);
		f.add(new TextField<String>("gcTitle", new PropertyModel<String>(this,
				"gcTitle")));
		f.add(new TextField<String>("gcMaxMarks", new PropertyModel<String>(
				this, "gcMaxMarks")));
		TextArea<String> ta;
		f.add(ta = new TextArea<String>("gcDesc", new PropertyModel<String>(this,
				"gcDesc")));
		ta.add(TinyMCEHelper.getDefaultTinyMCEBehavior());
		f.add(new TextField<String>("gcWeightage", new PropertyModel<String>(
				this, "gcWeightage")));

		f.add(new DropDownChoice<String>("gcType", typeRenderer.getModel(),
				typeRenderer.getOptions(), typeRenderer));
		f.add(new DropDownChoice<String>("gcGrading", gradeTypeRenderer
				.getModel(), gradeTypeRenderer.getOptions(), gradeTypeRenderer)
				.setVisible(false));

		f.add(new Button("gcSave"));
		f.add(new Button("gcDelete") {
			private static final long serialVersionUID = 5472384775369930587L;

			@Override
			public void onSubmit() {
				new GradingItemDAO(getORMInterface()).removeGradingItem(gItem
						.getObject());
				gradePage.setActivePanel(CourseGrading.GRADE_COMPONENTS);
				gItem = null;
				gcDesc = "";
				gcMaxMarks = "";
				gcTitle = "";
				gcWeightage = "";
				setError("");
			}

			@Override
			public boolean isVisible() {
				return gItem != null;
			}
		}.setDefaultFormProcessing(false));

		f.add(new Button("gcCancel") {
			private static final long serialVersionUID = -253841163650316881L;

			@Override
			public void onSubmit() {
				gradePage.setActivePanel(CourseGrading.GRADE_COMPONENTS);
				setError("");
			}
		}.setDefaultFormProcessing(false));
	}

	private void initModels() {
		if (gItem == null)
			return;
		GradingItem g = gItem.getObject();
		setGcTitle(g.getGradingItemName());
		setGcDesc(g.getGradingItemDesc());
		setGcMaxMarks("" + g.getMaxMarks());
		setGcWeightage("" + g.getWeightage());

		log.debug("Weightage = " + g.getWeightage() + "Model = "
				+ getGcWeightage());
		typeRenderer.setSelectedValue(g.getItemTypeString());
		gradeTypeRenderer.setSelectedValue(g.getGradingTypeString());
	}

	private void submit() {
		new GradingItemDAO(getORMInterface()).addGradingItem(gradePage
				.getCourseInstance().getObject(), getGcTitle(), getGcDesc(),
				gradeTypeRenderer.getSelection(), Double
						.parseDouble(gcMaxMarks), Double
						.parseDouble(gcWeightage), typeRenderer.getSelection());
	}

	private void submit(IModel<GradingItem> gradItem) {
		List<ItemGrade> igList = gradItem.getObject().getGrades();
		GradingItem g = gItem.getObject();
		Double d = g.getMaxMarks(); 
		if(d != Double.parseDouble(getGcMaxMarks()) && igList.size() > 0){
			setError("Cannot change the maximum marks as some students " +
					"have already been evaluated based on this.");
			return;
		}
		g.setCourseInstance(gradePage.getCourseInstance().getObject());
		g.setGradeType(GradingItem.GRADE_MARKS);
		g.setGradingItemDesc(getGcDesc());
		g.setGradingItemName(getGcTitle());
		g.setItemType(typeRenderer.getSelection());
		g.setMaxMarks(Double.parseDouble(getGcMaxMarks()));
		g.setWeightage(Double.parseDouble(getGcWeightage()));
		getORMInterface().commitAllChanges();
	}

	private boolean verify() {
		if (!StringUtil.isValid(getGcTitle())) {
			setError("Grade component name is required");
			return false;
		}
		
		if(StringUtil.isValid(getGcDesc()) && getGcDesc().length() > 400){
			setError("The description is too long. Please use a shorter description");
			return false;
		}

		if (!StringUtil.isValid(getGcWeightage())) {
			setError("Weightage is required. You may enter 0 if this component has no weightage in the course.");
			return false;
		} else {
			try {
				Double.parseDouble(gcMaxMarks);
			} catch (NumberFormatException e) {
				setError("Please enter a valid number for weightage.");
				return false;
			}
		}

		if (gradeTypeRenderer.getSelection() == GradingItem.GRADE_MARKS) {
			try {
				Double.parseDouble(gcMaxMarks);
			} catch (NumberFormatException e) {
				setError("Maximum marks are required if you have chosen a marks-based grading");
				return false;
			}
		}
		return true;
	}

	public void setGcTitle(String gcTitle) {
		this.gcTitle = gcTitle;
	}

	public String getGcTitle() {
		return gcTitle;
	}

	public void setGcMaxMarks(String gcMaxMarks) {
		this.gcMaxMarks = gcMaxMarks;
	}

	public String getGcMaxMarks() {
		return gcMaxMarks;
	}

	public void setGcDesc(String gcDesc) {
		this.gcDesc = gcDesc;
	}

	public String getGcDesc() {
		return gcDesc;
	}

	public String getGcWeightage() {
		return gcWeightage;
	}

	public void setGcWeightage(String gcWeightage) {
		this.gcWeightage = gcWeightage;
	}

	private String gcDesc = "";
	private String gcMaxMarks = "";
	private String gcTitle = "";
	private String gcWeightage = "";

	private final static HashMap<String, Integer> typeMap = new HashMap<String, Integer>();
	private final static HashMap<String, Integer> gradeTypeMap = new HashMap<String, Integer>();

	private GenericRenderer<Integer> typeRenderer = null;
	private GenericRenderer<Integer> gradeTypeRenderer = null;
	private IModel<GradingItem> gItem = null;
	public IModel<GradingItem> getgItem() {
		return gItem;
	}

	public void setgItem(IModel<GradingItem> gItem) {
		this.gItem = gItem;
		this.initModels();
	}

	private CourseGrading gradePage = null;

	static {
		typeMap.put("Examination", GradingItem.ITEM_EXAM);
		typeMap.put("Attendance", GradingItem.ITEM_ATTENDANCE);
		typeMap.put("Quiz", GradingItem.ITEM_COURSE_TEST);
		typeMap.put("Others", GradingItem.ITEM_OTHERS);

		gradeTypeMap.put("Grades", GradingItem.GRADE_LETTER);
		gradeTypeMap.put("Marks", GradingItem.GRADE_MARKS);
	}
}
